package com.vast.admin.service.impl;

import cn.hutool.core.date.DateTime;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.vast.admin.entity.Company;
import com.vast.admin.entity.CompanyAccount;
import com.vast.admin.entity.Contract;
import com.vast.admin.entity.DealRecord;
import com.vast.admin.entity.enums.OperatorEum;
import com.vast.admin.entity.enums.QueryOrderEnum;
import com.vast.admin.mapper.CompanyAccountMapper;
import com.vast.admin.mapper.CompanyMapper;
import com.vast.admin.mapper.DealRecordMapper;
import com.vast.admin.utils.QueryBuilder;
import com.vast.common.core.domain.entity.SysUser;
import com.vast.common.utils.StringUtils;
import com.vast.common.constant.MessageCode;
import com.vast.common.core.domain.Result;
import com.vast.system.exception.BusinessException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Service
@Slf4j
public class CompanyAccountService extends ServiceImpl<CompanyAccountMapper, CompanyAccount> {

    @Autowired
    private CompanyMapper companyMapper;

    @Autowired
    private DealRecordMapper dealRecordMapper;

    public IPage<CompanyAccount> queryList(Page<CompanyAccount> page, boolean listMode, String queryItems, String orderField, QueryOrderEnum order) {
        String companyName = "";
        if (listMode) {
            // size 小于 0 不在查询 total 及分页，自动调整为列表模式。
            // 注意！！这个地方自己控制好！！
            page.setSize(-1);
        }
        if (!StringUtils.isEmpty(queryItems)) {
            List<QueryBuilder> queryBuilders = new ArrayList<>();
            String[] queryItemArr = queryItems.split(";");
            if(queryItemArr.length > 0){
                for (String queryItemStr : queryItemArr) {
                    String[] itemArr = queryItemStr.split(",");
                    if(itemArr.length == 3){
                        String as = itemArr[1];
                        String params = itemArr[2];
                        if(!StringUtils.isEmpty(params)){
                            queryBuilders.add(new QueryBuilder(itemArr[0], OperatorEum.valueOf(as),itemArr[2]));
                        }
                    }
                }
            }

            if(!queryBuilders.isEmpty()){
               companyName = queryBuilders.get(0).getParams();
            }

        }

        IPage<CompanyAccount> clientAccountIPage = baseMapper.queryList(page,companyName);

        return clientAccountIPage;
    }

    @Transactional
    public boolean addOrUpdate(SysUser manager, CompanyAccount bean) {
        if(bean.getCompanyId() != null){
            CompanyAccount companyAccount = baseMapper.selectOne(new QueryWrapper<CompanyAccount>().eq(CompanyAccount.COL_COMPANY_ID, bean.getCompanyId()));
            if(companyAccount == null){ //账户不存在, 新建账户
                //添加操作记录
                DealRecord dealRecord = new DealRecord();
                dealRecord.setCreateBy(manager.getUserId());
                dealRecord.setUpdateBy(manager.getUserId());
                dealRecord.setCreateTime(DateTime.now());
                dealRecord.setUpdateTime(DateTime.now());
                dealRecord.setValid(1);
                dealRecord.setAccountId(bean.getCompanyId());
                dealRecord.setOperation(1);
                dealRecord.setPaymentType(Integer.parseInt(bean.getPaymentType()));
                dealRecord.setOriginalAmount(BigDecimal.ZERO);
                dealRecord.setRechargeAmount(bean.getMoney());
                dealRecord.setExtraAmount(BigDecimal.ZERO);
                dealRecordMapper.insert(dealRecord);

                bean.setCreateBy(manager.getUserId());
                bean.setUpdateBy(manager.getUserId());
                bean.setCreateTime(DateTime.now());
                bean.setUpdateTime(DateTime.now());
                bean.setValid(1);
                //添加
                baseMapper.insert(bean);
            }else{

                //交易类型
                int operation = bean.getOperation().intValue();

                //添加操作记录
                DealRecord dealRecord = new DealRecord();
                dealRecord.setCreateBy(manager.getUserId());
                dealRecord.setUpdateBy(manager.getUserId());
                dealRecord.setCreateTime(DateTime.now());
                dealRecord.setUpdateTime(DateTime.now());
                dealRecord.setValid(1);
                dealRecord.setRemark(bean.getRemark());
                dealRecord.setAccountId(bean.getCompanyId());
                dealRecord.setOperation(operation);
                dealRecord.setPaymentType(Integer.parseInt(bean.getPaymentType()));
                dealRecord.setOriginalAmount(companyAccount.getMoney());
                dealRecord.setRechargeAmount(bean.getMoney());
                dealRecord.setExtraAmount(BigDecimal.ZERO);
                dealRecordMapper.insert(dealRecord);

                companyAccount.setUpdateBy(manager.getUserId());
                bean.setUpdateTime(DateTime.now());
                if(operation == 1){//充值 加法
                    companyAccount.setMoney(companyAccount.getMoney().add(bean.getMoney()));
                }else if(operation == 2){//消费 减法
                    companyAccount.setMoney(companyAccount.getMoney().subtract(bean.getMoney()));
                }
                baseMapper.updateById(companyAccount);
            }
            return true;
        }else{
            return false;
        }

    }

    public CompanyAccount info(SysUser manager, Long id) {
        CompanyAccount bean = baseMapper.selectById(id);
        return bean;
    }


    public boolean delete(SysUser manager, Long[] ids) {

        List<Long> idsList = java.util.Arrays.asList(ids);
        int count = baseMapper.deleteBatchIds(idsList);

        return count == ids.length;

    }

    /**
     * 支付合同签署费用
     * @param contract
     * @param company
     * @param amount
     */
    @Transactional(rollbackFor = Exception.class)
    public void payContract(Contract contract, Company company, Double amount, SysUser manager) {
        CompanyAccount companyAccount = getByCompanyId(company.getId());
        BigDecimal originalAmount = companyAccount.getMoney();
        if (companyAccount == null) {
            throw new BusinessException(new Result(MessageCode.ERROR, "企业未开通预存账户，无法支付"));
        }
        BigDecimal money = originalAmount.subtract(new BigDecimal(amount));
        if (money.doubleValue() < 0) {
            throw new BusinessException(new Result(MessageCode.ERROR, "账户余额不足，无法支付"));
        }
        companyAccount = changeCompanyAccount(companyAccount, 2, new BigDecimal(amount), manager, 1);
        DealRecord dealRecord = new DealRecord();
        dealRecord.setCreateBy(manager.getUserId());
        dealRecord.setUpdateBy(manager.getUserId());
        dealRecord.setCreateTime(DateTime.now());
        dealRecord.setUpdateTime(DateTime.now());
        dealRecord.setValid(1);
        dealRecord.setContractName(contract.getContractName());
        dealRecord.setRemark("支付合同<" + contract.getContractNo() + ">签署费用");
        dealRecord.setContractName(contract.getContractName());
        dealRecord.setAccountId(companyAccount.getCompanyId());
        dealRecord.setOperation(2);
        dealRecord.setPaymentType(5);
        dealRecord.setOriginalAmount(originalAmount);
        dealRecord.setRechargeAmount(new BigDecimal(amount));
        dealRecord.setExtraAmount(BigDecimal.ZERO);
        dealRecordMapper.insert(dealRecord);
    }

    /**
     * 退费
     * @param contract
     * @param manager
     */
    @Transactional
    public void refund(Contract contract, SysUser manager) {
        CompanyAccount companyAccount = getByCompanyId(contract.getClientId());
        if (companyAccount == null) {
            throw new BusinessException(new Result(MessageCode.ERROR, "企业预存账户不存在"));
        }
        companyAccount = changeCompanyAccount(companyAccount, 1, new BigDecimal(contract.getContractAmount()), manager, 1);
        DealRecord dealRecord = new DealRecord();
        dealRecord.setCreateBy(manager.getUserId());
        dealRecord.setCreateTime(DateTime.now());
        dealRecord.setContractName(contract.getContractName());
        dealRecord.setRemark("合同<" + contract.getContractNo() + ">退款");
        dealRecord.setContractName(contract.getContractName());
        dealRecord.setAccountId(companyAccount.getCompanyId());
        dealRecord.setOperation(1);
        dealRecord.setPaymentType(6);
        dealRecord.setOriginalAmount(companyAccount.getMoney());
        dealRecord.setRechargeAmount(new BigDecimal(contract.getContractAmount()));
        dealRecord.setExtraAmount(BigDecimal.ZERO);
        dealRecordMapper.insert(dealRecord);
    }

    /**
     * 修改账户金额
     * @param companyAccount 账户
     * @param payType 操作类型 （1充值 2消费）
     * @param money 操作金额
     * @param manager
     * @return
     */
    private CompanyAccount changeCompanyAccount(CompanyAccount companyAccount, int payType, BigDecimal money, SysUser manager, int index) {
        BigDecimal amount = calAmount(companyAccount.getMoney(), money, payType);
        UpdateWrapper<CompanyAccount> companyAccountUpdateWrapper = new UpdateWrapper<>();
        companyAccountUpdateWrapper.set(CompanyAccount.COL_MONEY, amount)
                .set(CompanyAccount.COL_UPDATE_BY, manager.getUserId())
                .set(CompanyAccount.COL_UPDATE_TIME, new Date())
                .eq(CompanyAccount.COL_ID, companyAccount.getId())
                .eq(CompanyAccount.COL_MONEY, companyAccount.getMoney());
        if (super.update(companyAccountUpdateWrapper)) {
            companyAccount.setMoney(amount);
            return companyAccount;
        } else {
            if (index >= 10) {
                throw new BusinessException("修改账户金额失败");
            }
            log.warn("第{}次修改账户金额失败， 准备第{}次尝试！", index, index + 1);
            companyAccount = super.getById(companyAccount.getId());
            return changeCompanyAccount(companyAccount, payType, money, manager, ++ index);
        }
    }

    /**
     *
     * @param totalAmount 总金额
     * @param operatingAmount 操作金额
     * @param payType 操作类型（1充值 2消费）
     * @return
     */
    private BigDecimal calAmount(BigDecimal totalAmount, BigDecimal operatingAmount, int payType) {
        BigDecimal result;
        if (payType == 1) {
            result = totalAmount.add(operatingAmount);
        } else if (payType == 2) {
            result = totalAmount.subtract(operatingAmount);
        } else {
            throw new BusinessException("操作类型错误");
        }
        return result;
    }

    public CompanyAccount getByCompanyId(Long companyId) {
        QueryWrapper<CompanyAccount> companyAccountQueryWrapper = new QueryWrapper<>();
        companyAccountQueryWrapper.eq(CompanyAccount.COL_COMPANY_ID, companyId);
        return super.getOne(companyAccountQueryWrapper);
    }


    public IPage<CompanyAccount> queryCompanyAccountList(Page<CompanyAccount> page, CompanyAccount companyAccount) {

        return baseMapper.queryCompanyAccountList(page,companyAccount);
    }
}
